/*
 * @version: 1.0
 * @Author: zhl
 * @Date: 2021-12-14 11:35:15
 * @LastEditors: zhl
 * @LastEditTime: 2022-02-08 10:57:08
 * @Description: 文件实现描述
 */
#ifndef __MODBUS_MESSAGE_MANAGER_H__
#define __MODBUS_MESSAGE_MANAGER_H__

#include <iostream>
#include <memory>
#include <unordered_map>

#include "IModule.h"
#include "CConfigManager.h"
#include "CMosquittoManager.h"
#include "modbus.h"
#include "IChannel.h"
#include "CThreadPool.h"
#include "modbus_datastruct.h"
#include "global_data_struct.h"

#include <mutex>
#include <stack>

class MessageManager {
private:
    /* data */
    static MessageManager c_mm;
    CThreadPool c_thread_pool;
    std::mutex c_mutex;
    int64_t  c_req_id;
    stack<void *> c_parse_funcs;

private:
    int save_interaction_log(int64_t dev_id, int64_t task_id, uint8_t *req, int req_len, uint8_t *rep, int rep_len);
    int get_bit_value(uint8_t *rsp, uint8_t *data, int nb);
    int collect(IChannel *channel_ptr, int64_t dev_id, int64_t task_id, int slave_id, int reg_addr, int reg_count, int func_code, uint8_t *buf, int &len, int timeout=5000);
    int run_write_cmd(std::shared_ptr<CConfigManager> cm, IChannel *channel_ptr, std::shared_ptr<CMosquittoManager> mm, TASK_PARAMS *dev_reqs, std::shared_ptr<TERMINAL_DEVICE> dev);
    int read_cmd_handler(IChannel *channel_ptr, std::shared_ptr<TERMINAL_DEVICE> dev,  std::shared_ptr<MODBUS_COMMAND> point,  std::shared_ptr<COLLECT_DATA> collect_data, int timeout=5000);
    int run_read_cmd(std::shared_ptr<CConfigManager> cm, IChannel *channel_ptr, std::shared_ptr<CMosquittoManager> mm, TASK_PARAMS *dev_reqs, std::shared_ptr<TERMINAL_DEVICE> dev);
    int run_collect(std::shared_ptr<CConfigManager> cm, IChannel *channel_ptr, std::shared_ptr<CMosquittoManager> mm,  TASK_PARAMS *dev_reqs, std::shared_ptr<TERMINAL_DEVICE> dev);
    template<typename T>
    T   get_real_value(std::string formula, double scale, int decimal, std::string value);
    std::string get_real_value_str(std::shared_ptr<MODBUS_COMMAND> modbus_control, std::string value, std::string& vstr);
    std::shared_ptr<TERMINAL_DEVICE> get_parent_dev(std::shared_ptr<CConfigManager> cm, uint64_t parent_id);

    int  parse_parent_frame(std::shared_ptr<CConfigManager> cm, stack<void *> &parsers, uint8_t *data, int &len);
    int  parse_modbus_frame(uint8_t *frame, int frame_len, int func_code, uint8_t *target, int &target_len);

    int parent_run_collect(std::shared_ptr<CConfigManager> cm, 
                            IChannel *channel_ptr, 
                            std::shared_ptr<CMosquittoManager> mm, 
                            IModule &im, 
                            TASK_PARAMS *dev_reqs, 
                            std::shared_ptr<TERMINAL_DEVICE> dev);
    int parent_run_read_cmd(std::shared_ptr<CConfigManager> cm, 
                            IChannel *channel_ptr, 
                            std::shared_ptr<CMosquittoManager> mm, 
                            IModule &im, 
                            TASK_PARAMS *dev_reqs, 
                            std::shared_ptr<TERMINAL_DEVICE> dev);
    int parent_run_write_cmd(std::shared_ptr<CConfigManager> cm, 
                            IChannel *channel_ptr, 
                            std::shared_ptr<CMosquittoManager> mm, 
                            IModule &im, 
                            TASK_PARAMS *dev_reqs, 
                            std::shared_ptr<TERMINAL_DEVICE> dev);
public:
    
public:
    MessageManager(/* args */);
    ~MessageManager();
    
    static MessageManager &getInstance();
    void get_write_data_by_order(std::string byte_order, uint16_t *data);
    int  get_write_data(std::shared_ptr<MODBUS_COMMAND> modbus_control, std::string value, uint8_t *data, int *len);
    int  write_handler(std::shared_ptr<CConfigManager> cm, 
                    IChannel *channel_ptr, 
                    std::shared_ptr<CMosquittoManager> mm,
                    std::shared_ptr<TERMINAL_DEVICE> dev, 
                    std::shared_ptr<MODBUS_COMMAND> modbus_control, 
                    std::string &value);
    int  read_handler(std::shared_ptr<CConfigManager> cm, 
                    IChannel *channel_ptr, 
                    std::shared_ptr<CMosquittoManager> mm,
                    std::shared_ptr<TERMINAL_DEVICE> dev, 
                    int64_t task_id,
                    int64_t task_item_id, 
                    std::shared_ptr<COLLECT_DATA> collect_data);
    int  get_read_request_msg(int slave_id, int reg_addr, int reg_count, int func_code, uint8_t *buf, int &len);
    int  get_write_request_msg(int slave_id, int reg_addr, int nb, uint8_t *data, int func_code, uint8_t *buf, int &len);
    int  run(std::shared_ptr<CConfigManager> cm, IChannel *channel_ptr, std::shared_ptr<CMosquittoManager> mm, IModule &im, TASK_PARAMS *dev_reqs);
    int64_t  get_req_id();
    int  gw_write_handler(std::shared_ptr<MODBUS_COMMAND> modbus_control, std::string &value);
    int  gw_collect(int reg_addr, int nb, int func_code, uint8_t *buf, int &len);
    int  get_read_func_code(int funcCode);
    int  write_request_frame(int slave_id, std::shared_ptr<MODBUS_COMMAND> modbus_control, std::string &value, uint8_t *frame, int frame_len);
    int  read_request_frame(int slave_id, std::shared_ptr<MODBUS_REQUEST> modbus_request, uint8_t *frame, int frame_len);
    int  no_parent_dev_handle(std::shared_ptr<CConfigManager> cm, 
                            IChannel *channel_ptr, 
                            std::shared_ptr<CMosquittoManager> mm, 
                            IModule &im, 
                            TASK_PARAMS *dev_reqs, 
                            std::shared_ptr<TERMINAL_DEVICE> dev);
    int  parent_dev_handle(std::shared_ptr<CConfigManager> cm, 
                            IChannel *channel_ptr, 
                            std::shared_ptr<CMosquittoManager> mm, 
                            IModule &im, 
                            TASK_PARAMS *dev_reqs, 
                            std::shared_ptr<TERMINAL_DEVICE> dev);
    int  package_parent_frame(std::shared_ptr<CConfigManager> cm, 
                              IModule &im, 
                              stack<void *> &parsers, 
                              std::shared_ptr<TERMINAL_DEVICE> pdev, 
                              uint8_t *data, int &len);

};




#endif /* __MODBUS_MESSAGE_MANAGER_H__ */